SREG (Status Register)
0. 주요 용어 정의 (Glossary)
본 문서에서 사용하는 핵심 용어의 정의는 다음과 같습니다.
* SREG (Status Register): CPU의 현재 상태와 연산 결과 특성을 저장하는 특수 목적 레지스터.
* ALU (Arithmetic Logic Unit): 산술 논리 연산을 수행하는 CPU의 핵심 장치.
* Flag (플래그): 특정 조건의 발생 여부를 나타내는 1비트 표시자.
* ISR (Interrupt Service Routine): 인터럽트 발생 시 실행되는 특수 함수(서비스 루틴).
* MSB (Most Significant Bit): 데이터의 최상위 비트. 부호 있는 정수에서는 부호 비트로 사용됨.
1. 개요
SREG(Status Register, 상태 레지스터)는 CPU의 현재 상태 정보와 최근에 수행된 산술 및 논리 연산의 결과 특성을 저장하는 특수 목적 레지스터이다. SREG는 각 비트가 독립적인 플래그(Flag)로 작동하며, CPU는 이 플래그 값들을 참조하여 조건부 분기(Conditional Branching)를 수행하거나 시스템의 전역적인 동작 모드를 결정한다.
2. 구조 및 비트 구성
SREG는 일반적으로 8비트 또는 그 이상의 크기를 가지며, 각 비트는 특정 상태를 나타낸다.
※ 아래 구성은 ATmega328P 등 AVR 아키텍처 기준이며, 타 CPU(x86, ARM 등)에서는 비트 위치와 종류가 다릅니다.
| 비트 번호 |
플래그 이름 |
약어 |
설명 |
읽기/쓰기 |
| Bit 7 |
Global Interrupt Enable |
I |
전역 인터럽트 활성화 여부 결정 |
R/W |
| Bit 6 |
Total Carry Flag |
T |
연산 결과의 전체 캐리 발생 여부 |
R/W |
| Bit 5 |
Half Carry Flag |
H |
하위 4비트에서 상위 4비트로의 캐리 발생 여부 |
R/W |
| Bit 4 |
Negative Flag |
N |
연산 결과의 최상위 비트(MSB)가 1인지 여부 (음수 판별) |
R/W |
| Bit 3 |
Zero Flag |
Z |
연산 결과가 0인지 여부 |
R/W |
| Bit 2 |
Carry Flag |
C |
산술 연산 시 자리 올림 또는 빌림 발생 여부 |
R/W |
| Bit 1 |
Overflow Flag |
V |
부호 있는 연산 시 결과가 표현 범위를 초과했는지 여부 |
R/W |
| Bit 0 |
Single Cycle Mode |
S |
단일 사이클 모드 활성화 여부 |
R/W |
3. 주요 상태 플래그 (Status Flags)
상태 플래그는 ALU(Arithmetic Logic Unit)의 연산 결과에 따라 하드웨어적으로 자동 갱신된다.
- Zero Flag (Z): 연산 결과가 모든 비트가 0일 때 1로 설정된다. 두 값이 같은지 비교(
CMP 명령어)할 때, 결과가 0이면 Z 플래그가 1이 되어 '같음'을 판별한다.
- Carry Flag (C): 부호 없는 정수 연산에서 최상위 비트(MSB)에서 자리 올림(Carry)이나 빌림(Borrow)이 발생했을 때 설정된다. 다정밀도 연산(Multi-precision arithmetic)에서 하위 바이트의 결과를 상위 바이트로 전달할 때 사용된다.
- Negative Flag (N): 결과의 MSB가 1일 때 설정된다. 2의 보수(2's Complement) 표현법에서 MSB는 부호 비트이므로, 이 플래그를 통해 결과가 음수인지 확인한다.
- Overflow Flag (V): 부호 있는 정수 연산에서 결과가 해당 데이터 타입이 표현할 수 있는 범위를 벗어났을 때 설정된다.
- 발생 사례: 8비트 부호 있는 정수(범위: -128 ~ 127) 연산 시
- $127 + 1 = 128$ $\rightarrow$ 결과가 $-128$로 해석됨 (양수 + 양수 = 음수 $\rightarrow$ V=1)
- $-128 + (-1) = -129$ $\rightarrow$ 결과가 $127$로 해석됨 (음수 + 음수 = 양수 $\rightarrow$ V=1)
4. 제어 플래그 및 전역 인터럽트
상태 플래그와 달리 제어 플래그는 프로그래머가 소프트웨어적으로 설정하여 CPU의 동작 방식을 제어한다.
- Global Interrupt Enable (I): 이 비트가 1이면 개별 인터럽트 허용 설정이 된 인터럽트들이 CPU에 신호를 보낼 수 있다. 0으로 설정하면 모든 인터럽트가 무시된다.
- 중요성: 임계 구역(Critical Section) 내에서 데이터 일관성을 유지하기 위해 잠시 인터럽트를 비활성화(
CLI 명령어)하고, 작업 완료 후 다시 활성화(SEI 명령어)하는 방식으로 사용된다.
5. 동작 원리와 활용
CPU는 연산 직후 SREG의 상태를 확인하여 다음에 실행할 명령어의 주소를 결정한다.
5.1 상태 천이도 (State Transition)
ALU 연산 결과에 따라 모든 관련 플래그는 동시에(Parallel) 업데이트된다.
graph TD
A[ALU 연산 수행] --> B{결과 == 0?}
B -- Yes --> C[Z = 1]
B -- No --> D[Z = 0]
A --> E{MSB == 1?}
E -- Yes --> F[N = 1]
E -- No --> G[N = 0]
A --> H{Carry 발생?}
H -- Yes --> I[C = 1]
H -- No --> J[C = 0]
A --> K{부호 오버플로?}
K -- Yes --> L[V = 1]
K -- No --> M[V = 0]
C & D & F & G & I & J & L & M --> Z[동시 갱신 완료]
5.2 코드 예시
특정 값이 0인지 확인하여 분기하는 어셈블리 및 C언어의 논리적 구조이다.
Assembly (AVR 예시):
SUB R16, R17 ; R16 = R16 - R17 (연산 결과에 따라 SREG 갱신)
BRNE Label_NotEqual ; Z 플래그가 0이면(Not Equal) Label_NotEqual로 분기
; Z 플래그가 1이면(Equal) 아래 코드를 계속 실행
C Language (추상화):
if (a == b) {
// 내부적으로는 CMP a, b 수행 후 SREG의 Z 플래그가 1인지 확인
do_something();
}
6. SREG 관련 주요 명령어
SREG의 값을 읽거나 수정, 또는 SREG의 상태에 따라 분기하는 주요 명령어 목록이다.
| 명령어 |
풀네임 |
기능 |
비고 |
| CLI |
Clear Global Interrupt |
SREG의 I 비트를 0으로 설정 |
인터럽트 금지 |
| SEI |
Set Global Interrupt |
SREG의 I 비트를 1로 설정 |
인터럽트 허용 |
| BRNE |
Branch if Not Equal |
Z 플래그가 0일 때 분기 |
Z == 0 |
| BREQ |
Branch if Equal |
Z 플래그가 1일 때 분기 |
Z == 1 |
| BRCS |
Branch if Carry Set |
C 플래그가 1일 때 분기 |
C == 1 |
| BRMI |
Branch if Minus |
N 플래그가 1일 때 분기 |
N == 1 |
| PUSH/POP |
Push/Pop SREG |
SREG 값을 스택에 저장하거나 복원 |
SREG는 특수 레지스터이므로 일반 레지스터와 PUSH/POP 방식이 다를 수 있음 (예: AVR의 경우 PUSH SREG 전용 명령어 존재) |
7. 타 CPU 레지스터와의 비교
SREG는 아키텍처마다 명칭이 다르지만 유사한 기능을 수행한다.
| 구분 |
AVR (SREG) |
x86 (EFLAGS/RFLAGS) |
ARM (CPSR) |
| 명칭 |
Status Register |
Flags Register |
Current Program Status Register |
| 크기 |
8-bit |
32/64-bit |
32-bit |
| 주요 특징 |
단순한 구조, 임베디드 최적화 |
매우 복잡한 플래그 세트 (Trap, IF 등) |
모드 전환(User/SVC) 정보 포함 |
| 인터럽트 제어 |
I 비트로 통합 제어 |
IF(Interrupt Flag) 비트 사용 |
I, F 비트로 단계적 제어 |
8. 주의사항 및 최적화
8.1 ISR 내 SREG 보존
ISR(Interrupt Service Routine)은 메인 프로그램의 실행 흐름을 갑자기 끊고 진입한다. 이때 메인 프로그램이 사용하던 SREG의 플래그 값(예: 연산 직후의 Z 플래그)이 ISR 내의 연산으로 인해 덮어씌워지면, ISR 종료 후 메인 프로그램으로 돌아왔을 때 잘못된 분기 결정이 내려질 수 있다.
저장 및 복원의 필요성:
메인 루틴의 연산 결과(SREG 상태)를 보존하지 않은 채 ISR이 실행되면, ISR 내부의 ALU 연산이 SREG를 변경하게 된다. 이로 인해 메인 루틴의 if문이나 loop 조건 판별에 사용될 플래그가 오염되어 프로그램이 오작동하게 된다. 따라서 컨텍스트 보존을 위해 반드시 저장과 복원 과정이 필요하다.
해결 방법:
1. ISR 진입 직후 PUSH SREG를 통해 현재 상태를 스택에 저장한다.
2. ISR의 모든 작업을 완료한 후 POP SREG를 통해 원래 상태를 복원한다.
8.2 컨텍스트 스위칭 (Context Switching)
멀티태스킹 환경에서 OS가 태스크를 전환할 때, SREG는 해당 태스크의 컨텍스트(Context, 실행 상태)의 핵심 요소이다. 따라서 TCB(Task Control Block)에 SREG 값을 저장하여, 다시 해당 태스크가 실행될 때 이전의 연산 상태와 인터럽트 설정이 그대로 유지되도록 해야 한다.
# SREG (Status Register)
## 0. 주요 용어 정의 (Glossary)
본 문서에서 사용하는 핵심 용어의 정의는 다음과 같습니다.
* **SREG (Status Register):** CPU의 현재 상태와 연산 결과 특성을 저장하는 특수 목적 레지스터.
* **ALU (Arithmetic Logic Unit):** 산술 논리 연산을 수행하는 CPU의 핵심 장치.
* **Flag (플래그):** 특정 조건의 발생 여부를 나타내는 1비트 표시자.
* **ISR (Interrupt Service Routine):** 인터럽트 발생 시 실행되는 특수 함수(서비스 루틴).
* **MSB (Most Significant Bit):** 데이터의 최상위 비트. 부호 있는 정수에서는 부호 비트로 사용됨.
## 1. 개요
**SREG(Status Register, 상태 레지스터)**는 CPU의 현재 상태 정보와 최근에 수행된 산술 및 논리 연산의 결과 특성을 저장하는 특수 목적 레지스터이다. SREG는 각 비트가 독립적인 **플래그(Flag)**로 작동하며, CPU는 이 플래그 값들을 참조하여 조건부 분기(Conditional Branching)를 수행하거나 시스템의 전역적인 동작 모드를 결정한다.
## 2. 구조 및 비트 구성
SREG는 일반적으로 8비트 또는 그 이상의 크기를 가지며, 각 비트는 특정 상태를 나타낸다.
※ 아래 구성은 ATmega328P 등 AVR 아키텍처 기준이며, 타 CPU(x86, ARM 등)에서는 비트 위치와 종류가 다릅니다.
| 비트 번호 | 플래그 이름 | 약어 | 설명 | 읽기/쓰기 |
| :--- | :--- | :---: | :--- | :---: |
| Bit 7 | Global Interrupt Enable | **I** | 전역 인터럽트 활성화 여부 결정 | R/W |
| Bit 6 | Total Carry Flag | **T** | 연산 결과의 전체 캐리 발생 여부 | R/W |
| Bit 5 | Half Carry Flag | **H** | 하위 4비트에서 상위 4비트로의 캐리 발생 여부 | R/W |
| Bit 4 | Negative Flag | **N** | 연산 결과의 최상위 비트(MSB)가 1인지 여부 (음수 판별) | R/W |
| Bit 3 | Zero Flag | **Z** | 연산 결과가 0인지 여부 | R/W |
| Bit 2 | Carry Flag | **C** | 산술 연산 시 자리 올림 또는 빌림 발생 여부 | R/W |
| Bit 1 | Overflow Flag | **V** | 부호 있는 연산 시 결과가 표현 범위를 초과했는지 여부 | R/W |
| Bit 0 | Single Cycle Mode | **S** | 단일 사이클 모드 활성화 여부 | R/W |
## 3. 주요 상태 플래그 (Status Flags)
상태 플래그는 **ALU(Arithmetic Logic Unit)**의 연산 결과에 따라 하드웨어적으로 자동 갱신된다.
* **Zero Flag (Z):** 연산 결과가 모든 비트가 0일 때 1로 설정된다. 두 값이 같은지 비교(`CMP` 명령어)할 때, 결과가 0이면 Z 플래그가 1이 되어 '같음'을 판별한다.
* **Carry Flag (C):** 부호 없는 정수 연산에서 최상위 비트(MSB)에서 자리 올림(Carry)이나 빌림(Borrow)이 발생했을 때 설정된다. 다정밀도 연산(Multi-precision arithmetic)에서 하위 바이트의 결과를 상위 바이트로 전달할 때 사용된다.
* **Negative Flag (N):** 결과의 MSB가 1일 때 설정된다. 2의 보수(2's Complement) 표현법에서 MSB는 부호 비트이므로, 이 플래그를 통해 결과가 음수인지 확인한다.
* **Overflow Flag (V):** 부호 있는 정수 연산에서 결과가 해당 데이터 타입이 표현할 수 있는 범위를 벗어났을 때 설정된다.
* **발생 사례:** 8비트 부호 있는 정수(범위: -128 ~ 127) 연산 시
* $127 + 1 = 128$ $\rightarrow$ 결과가 $-128$로 해석됨 (양수 + 양수 = 음수 $\rightarrow$ **V=1**)
* $-128 + (-1) = -129$ $\rightarrow$ 결과가 $127$로 해석됨 (음수 + 음수 = 양수 $\rightarrow$ **V=1**)
## 4. 제어 플래그 및 전역 인터럽트
상태 플래그와 달리 제어 플래그는 프로그래머가 소프트웨어적으로 설정하여 CPU의 동작 방식을 제어한다.
* **Global Interrupt Enable (I):** 이 비트가 1이면 개별 인터럽트 허용 설정이 된 인터럽트들이 CPU에 신호를 보낼 수 있다. 0으로 설정하면 모든 인터럽트가 무시된다.
* **중요성:** 임계 구역(Critical Section) 내에서 데이터 일관성을 유지하기 위해 잠시 인터럽트를 비활성화(`CLI` 명령어)하고, 작업 완료 후 다시 활성화(`SEI` 명령어)하는 방식으로 사용된다.
## 5. 동작 원리와 활용
CPU는 연산 직후 SREG의 상태를 확인하여 다음에 실행할 명령어의 주소를 결정한다.
### 5.1 상태 천이도 (State Transition)
ALU 연산 결과에 따라 모든 관련 플래그는 **동시에(Parallel)** 업데이트된다.
```mermaid
graph TD
A[ALU 연산 수행] --> B{결과 == 0?}
B -- Yes --> C[Z = 1]
B -- No --> D[Z = 0]
A --> E{MSB == 1?}
E -- Yes --> F[N = 1]
E -- No --> G[N = 0]
A --> H{Carry 발생?}
H -- Yes --> I[C = 1]
H -- No --> J[C = 0]
A --> K{부호 오버플로?}
K -- Yes --> L[V = 1]
K -- No --> M[V = 0]
C & D & F & G & I & J & L & M --> Z[동시 갱신 완료]
```
### 5.2 코드 예시
특정 값이 0인지 확인하여 분기하는 어셈블리 및 C언어의 논리적 구조이다.
**Assembly (AVR 예시):**
```assembly
SUB R16, R17 ; R16 = R16 - R17 (연산 결과에 따라 SREG 갱신)
BRNE Label_NotEqual ; Z 플래그가 0이면(Not Equal) Label_NotEqual로 분기
; Z 플래그가 1이면(Equal) 아래 코드를 계속 실행
```
**C Language (추상화):**
```c
if (a == b) {
// 내부적으로는 CMP a, b 수행 후 SREG의 Z 플래그가 1인지 확인
do_something();
}
```
## 6. SREG 관련 주요 명령어
SREG의 값을 읽거나 수정, 또는 SREG의 상태에 따라 분기하는 주요 명령어 목록이다.
| 명령어 | 풀네임 | 기능 | 비고 |
| :--- | :--- | :--- | :--- |
| **CLI** | Clear Global Interrupt | SREG의 I 비트를 0으로 설정 | 인터럽트 금지 |
| **SEI** | Set Global Interrupt | SREG의 I 비트를 1로 설정 | 인터럽트 허용 |
| **BRNE** | Branch if Not Equal | Z 플래그가 0일 때 분기 | `Z == 0` |
| **BREQ** | Branch if Equal | Z 플래그가 1일 때 분기 | `Z == 1` |
| **BRCS** | Branch if Carry Set | C 플래그가 1일 때 분기 | `C == 1` |
| **BRMI** | Branch if Minus | N 플래그가 1일 때 분기 | `N == 1` |
| **PUSH/POP** | Push/Pop SREG | SREG 값을 스택에 저장하거나 복원 | SREG는 특수 레지스터이므로 일반 레지스터와 PUSH/POP 방식이 다를 수 있음 (예: AVR의 경우 `PUSH SREG` 전용 명령어 존재) |
## 7. 타 CPU 레지스터와의 비교
SREG는 아키텍처마다 명칭이 다르지만 유사한 기능을 수행한다.
| 구분 | AVR (SREG) | x86 (EFLAGS/RFLAGS) | ARM (CPSR) |
| :--- | :--- | :--- | :--- |
| **명칭** | Status Register | Flags Register | Current Program Status Register |
| **크기** | 8-bit | 32/64-bit | 32-bit |
| **주요 특징** | 단순한 구조, 임베디드 최적화 | 매우 복잡한 플래그 세트 (Trap, IF 등) | 모드 전환(User/SVC) 정보 포함 |
| **인터럽트 제어** | I 비트로 통합 제어 | IF(Interrupt Flag) 비트 사용 | I, F 비트로 단계적 제어 |
## 8. 주의사항 및 최적화
### 8.1 ISR 내 SREG 보존
**ISR(Interrupt Service Routine)**은 메인 프로그램의 실행 흐름을 갑자기 끊고 진입한다. 이때 메인 프로그램이 사용하던 SREG의 플래그 값(예: 연산 직후의 Z 플래그)이 ISR 내의 연산으로 인해 덮어씌워지면, ISR 종료 후 메인 프로그램으로 돌아왔을 때 잘못된 분기 결정이 내려질 수 있다.
**저장 및 복원의 필요성:**
메인 루틴의 연산 결과(SREG 상태)를 보존하지 않은 채 ISR이 실행되면, ISR 내부의 ALU 연산이 SREG를 변경하게 된다. 이로 인해 메인 루틴의 `if`문이나 `loop` 조건 판별에 사용될 플래그가 오염되어 프로그램이 오작동하게 된다. 따라서 **컨텍스트 보존**을 위해 반드시 저장과 복원 과정이 필요하다.
**해결 방법:**
1. ISR 진입 직후 `PUSH SREG`를 통해 현재 상태를 스택에 저장한다.
2. ISR의 모든 작업을 완료한 후 `POP SREG`를 통해 원래 상태를 복원한다.
### 8.2 컨텍스트 스위칭 (Context Switching)
멀티태스킹 환경에서 OS가 태스크를 전환할 때, SREG는 해당 태스크의 **컨텍스트(Context, 실행 상태)**의 핵심 요소이다. 따라서 TCB(Task Control Block)에 SREG 값을 저장하여, 다시 해당 태스크가 실행될 때 이전의 연산 상태와 인터럽트 설정이 그대로 유지되도록 해야 한다.